/* TeXMLLikeCharConv.c Program to convert characteres a la TeXML 
 *  (see http://getfo.org/texml/)
 *
 * Andy Black
 * 08-July-2009
 *
 */

#include <stdio.h>
#include <ctype.h>

#ifdef _MSC_VER
#include <stdlib.h>
#endif

/*****************************************************************************
 *  FUNCTION PROTO-TYPING
 */

#ifdef __STDC__		/* not all compilers support proto-typing */
#define P(s) s
#else
#define P(s) ()
#endif

       void  main      P( (int argc, char **argv));

#undef P

#define LEFTWEDGE "\\textless{}"
#define RIGHTWEDGE "\\textgreater{}"

void main(argc, argv)
     int argc;
     char *argv[];
{
  int c;			/* character read */
  int c1;			/* first next character read */
  int c2;			/* second next character read */
  int c3;			/* third next character read */
  int c4;			/* fourth next character read */
  int fInXmlElement = 0;
  FILE *fp, *fopen();

  				/* for each file in the command line ... */
      if ((fp = fopen(argv[1], "r")) == NULL)
	{
	  fprintf(stderr,"%s: Could not open file %s\n", argv[0], argv[1]);
	  exit(1);
	}
	while((c=getc(fp)) != EOF)
	{
	  switch (c)
	    {
	    case '\\':
	      fputs("\\textbackslash{}", stdout);
	      break;
	    case '{':
	      fputs("\\{", stdout);
	      break;
	    case '}':
	      fputs("\\}", stdout);
	      break;
	    case '$':
	      fputs("\\textdollar{}", stdout);
	      break;
	    case '[':
	      fputs("\\textsquarebracketleft{}", stdout);
	      break;
	    case ']':
	      fputs("\\textsquarebracketright{}", stdout);
	      break;
	    case '&':
	      c1=getc(fp);
	      if (c1 == 'l'  || c1 == 'g')
		{
		  c2=getc(fp);
		  if (c2 != EOF && (c2 == 't' || c2 == 'e'))
		    {
		      c3=getc(fp);
		      if (c3 != EOF && c3 == ';')
			{
			  /* found "&lt;", "&le;", "&gt;" or "&ge;" */
			  if (c1 == 'l')
			    fputs(LEFTWEDGE, stdout);			      
			  else
			    fputs(RIGHTWEDGE, stdout);
			  if (c2 == 'e')
			    putc('=', stdout);
			  break;
			}
		      else
			{	/* c3 is EOF */
			  putc(c, stdout);
			  putc(c1, stdout);
			  putc(c2, stdout);
			  break;
			}
		    }
		  else
		    {		/* c2 is EOF */
		      putc(c, stdout);
		      putc(c1, stdout);
		      break;
		    }
		}
	      if (c1 == 'a')
		{
		  c2=getc(fp);
		  if (c2 != EOF && c2 == 'm')
		    {
		      c3=getc(fp);
		      if (c3 != EOF && c3 == 'p')
			{
			  c4 = getc(fp);
			  if (c4 != EOF && c4 == ';')
			    {
			      /* found "&amp;" so add backslash in front of it.
			         This will then come out OK in the XML and the
			         TeX, too. */
			      fputs("\\&amp;", stdout);
			      break;
			    }
			  else
			    {	/* c4 is EOF */
			      putc(c, stdout);
			      putc(c1, stdout);
			      putc(c2, stdout);
			      putc(c3, stdout);
			      break;
			    }
			}
		      else
			{	/* c3 is EOF */
			  putc(c, stdout);
			  putc(c1, stdout);
			  putc(c2, stdout);
			  break;
			}
		    }
		  else
		    {		/* c2 is EOF */
		      putc(c, stdout);
		      putc(c1, stdout);
		      break;
		    }
		}
	      // need to take care of &#x..; cases for < > and &
	      // & = &#x26; &#38; &#o46; - or whatever octal is...
	      // < = &#x3c; &#60; &#o74;
	      // > = &#x3e; &#62; &#o76;
	      /* c1 is not 'a' */
	      putc(c, stdout);
	      if (c1 != EOF)
		putc(c1, stdout);
	      break;
	    case '#':
	      fputs("\\#", stdout);
	      break;
	    case '^':
	      fputs("\\^{}", stdout);
	      break;
	    case '_':
	      fputs("\\_", stdout);
	      break;
	    case '~':
	      fputs("\\textasciitilde{}", stdout);
	      break;
	    case '%':
	      fputs("\\%", stdout);
	      break;
	    case '|':
	      fputs("\\textbar{}", stdout);
	      break;
	    case '<':
	      fInXmlElement=0;	/* be pessimistic */
	      c1=getc(fp);
	      if (c1 != EOF && (c1 == '?' || c1 == '/'  || c1 == '!'))
		{
		  /* skip these; they are part of the XML */
		  fInXmlElement = 1;
		  putc(c, stdout);
		  putc(c1, stdout);
		  break;
		}
	      if (c1 == 't')
		{
		  c2=getc(fp);
		  if (c2 != EOF && c2 == 'e')
		    {
		      c3=getc(fp);
		      if (c3 != EOF && c3 == 'x')
			{
			  c4=getc(fp);
			  if (c4 != EOF && c4 == ':')
			    {
			      /* found "<tex:"; skip it */
			      fInXmlElement = 1;
			      putc(c, stdout);
			      putc(c1, stdout);
			      putc(c2, stdout);
			      putc(c3, stdout);
			      putc(c4, stdout);
			      break;
			    }
			  else
			    {	/* c4 is EOF */
			      fputs(LEFTWEDGE, stdout);
			      putc(c1, stdout);
			      putc(c2, stdout);
			      putc(c3, stdout);
			      break;
			    }
			}
		      else
			{	/* c3 is EOF */
			  fputs(LEFTWEDGE, stdout);
			  putc(c1, stdout);
			  putc(c2, stdout);
			  break;
			}
		    }
		  else
		    {		/* c2 is EOF */
		      fputs(LEFTWEDGE, stdout);
		      putc(c1, stdout);
		      break;
		    }
		}
	      /* c1 is not 't' */
	      fputs(LEFTWEDGE, stdout);
	      if (c1 != EOF)
		putc(c1, stdout);
	      break;
	    case '>':
	      if (fInXmlElement == 1)
		putc(c, stdout);
	      else
		fputs(RIGHTWEDGE, stdout);
	      break;
/*
  # not special but typography
  u'\u00a9': r'\textcopyright{}',
  u'\u2011': r'\mbox{-}'
*/
	    default:
	      putc(c, stdout);
	      break;
	    }

	}
      fclose(fp);	

}
